
// v-sync-height="'.app'" v-sync-height="['.app']" | 指定和 .app 同步高度,只要组件更新都会同步, .app 也可以换成 #app(只要是CSS支持的选择器都可以,但是只建议使用 ID 和 class 选择器)
// v-sync-height="['.app', update]" | 指定和 .app 同步高度,当 update 变量由 false -> true 时会同步高度,其他情况都不会同步高度, true -> true 也不行
// v-sync-height="['.app', undefined]" 指定和 .app 同步高度,只要组件更新都会同步,不建议这样写
// v-sync-height="['.app', undefined, '.other']" 指定和 .app 同步高度,只要组件更新都会同步,当 .app 高度小于 .parent 的高度时,会同步 .other 的高度
// v-sync-height="['.app', update, '.other']"
export default {
  componentUpdated(el, binding) {
    const isArray = Array.isArray(binding.value)
    const target = isArray ? binding.value[0] : binding.value
    const alternative = isArray ? binding.value[2] : null
    let flag
    if (isArray) {
      if (binding.value[1] === undefined) {
        flag = true
      } else {
        flag = !binding.oldValue[1] && binding.value[1]
      }
    } else {
      flag = true
    }
    if (flag) {
      setTimeout(() => {
        el.style.height = 0
        let alternativeDom
        let height
        if (alternative) {
          alternativeDom = traverseParent(el, alternative)
        }
        const targetDom = el.parentNode.querySelector(target)
        if (alternativeDom) {
          const alternativeStyle = window.getComputedStyle(alternativeDom)
          // 只需要上下的高度
          const alternativePadding = parseFloat(alternativeStyle.getPropertyValue('padding-top')) + parseFloat(alternativeStyle.getPropertyValue('padding-bottom'))
          height = targetDom.scrollHeight < (alternativeDom.scrollHeight - alternativePadding) ? (alternativeDom.scrollHeight - alternativePadding) : targetDom.scrollHeight
        } else {
          height = targetDom.scrollHeight
        }
        el.style.height = height + 'px'
      })
    }
  }
}

function traverseParent(el, selector) {
  if (el.parentNode) {
    const alternativeDom = el.parentNode.querySelector(selector)
    if (!alternativeDom) {
      return traverseParent(el.parentNode, selector)
    } else {
      return alternativeDom
    }
  } else {
    return null
  }
}
